package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.service.TestService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author atguigu-mqx
 * @ClassName TestServiceImpl
 * @description: TODO
 * @date 2024年01月02日
 * @version: 1.0
 */
@Service
public class TestServiceImpl implements TestService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private RedissonClient redissonClient;

    @Override
    public void testLock() {
         /*
        1.  先在缓存中设置一个key num = 0
        2.  从缓存中获取num
            true:   并对 num进行+1 放入缓存
            false:  return;
         */
        RLock lock = redissonClient.getLock("lock");
        //  上锁：
          lock.lock();
        //  第一个参数：锁的有效期，第二个时间单位
        //  lock.lock(10, TimeUnit.SECONDS);
        //  第一个参数：最大等待时间，第二个参数：锁的有效期，第三个时间单位
        boolean res = false;
        try {
            res = lock.tryLock(100, 10, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if (res){
            try {
                String num = this.redisTemplate.opsForValue().get("num");
                //  判断
                if (StringUtils.isEmpty(num)) {
                    return;
                }
                //  转换
                int numValue = Integer.parseInt(num);
                redisTemplate.opsForValue().set("num",String.valueOf(++numValue));
            } catch (NumberFormatException e) {
                throw new RuntimeException(e);
            } finally {
                //  解锁
                lock.unlock();
            }
        }else {
            System.out.println("未获取到锁...");
        }


    }

//    @Override
//    public void testLock() {
//        //  index2;
//        /*
//        1.  先在缓存中设置一个key num = 0
//        2.  从缓存中获取num
//            true:   并对 num进行+1 放入缓存
//            false:  return;
//         */
//        //  setnx key value;
//        //  Boolean result = this.redisTemplate.opsForValue().setIfAbsent("lock", "ok");
//        //  set lock ok nx ex 10
//        String token = UUID.randomUUID().toString();
//        Boolean result = this.redisTemplate.opsForValue().setIfAbsent("lock", token,3,TimeUnit.SECONDS);
//        if (result){
//            //  setnx lock ok
//            String num = redisTemplate.opsForValue().get("num");
////            this.redisTemplate.expire("lock",3, TimeUnit.SECONDS);
//            //  判断
//            if (StringUtils.isEmpty(num)){
//                return;
//            }
//            //  转换
//            int numValue = Integer.parseInt(num);
//            //  int i = 1/0;
//            //  ttl key;
//            //  while ()
//            //            Thread thread = new Thread(() -> {
//            //                if (this.redisTemplate.getExpire("lock")<1){
//            //                    // expire
//            //                    this.redisTemplate.expire("lock",3,TimeUnit.SECONDS);
//            //                }
//            //            });
//            //            //  设置守护线程.
//            //            thread.setDaemon(true);
//            //            thread.start();
//            //  不为空。
//            redisTemplate.opsForValue().set("num",String.valueOf(++numValue));
//            //  删除锁 不能防止多线程操作。
//            //            while (token.equals(redisTemplate.opsForValue().get("lock"))){
//            //                //  index1 --del;
//            //                this.redisTemplate.delete("lock");
//            //            }
//
//            String scriptText ="if redis.call(\"get\",KEYS[1]) == ARGV[1]\n" +
//                    "then\n" +
//                    "    return redis.call(\"del\",KEYS[1])\n" +
//                    "else\n" +
//                    "    return 0\n" +
//                    "end";
//            //  第一个参数：设置lua脚本对象
//            DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
//            redisScript.setScriptText(scriptText);
//            redisScript.setResultType(Long.class);
//            //  第二个参数 缓存key  第三个参数key对应的value
//            this.redisTemplate.execute(redisScript, Arrays.asList("lock"),token);
//        } else {
//            //  没有获取到锁.
//            try {
//                Thread.sleep(100);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            testLock();
//        }
//
//    }
}
